package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.vo.PageResult;
import com.leyou.item.dto.BrandDTO;
import com.leyou.item.pojo.TbBrand;
import com.leyou.item.mapper.TbBrandMapper;
import com.leyou.item.pojo.TbCategory;
import com.leyou.item.pojo.TbCategoryBrand;
import com.leyou.item.service.TbBrandService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.item.service.TbCategoryBrandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 品牌表，一个品牌下有多个商品（spu），一对多关系 服务实现类
 * </p>
 *
 * @author leyou
 * @since 2020-02-29
 */
@Service
public class TbBrandServiceImpl extends ServiceImpl<TbBrandMapper, TbBrand> implements TbBrandService {
    @Autowired
    private TbCategoryBrandService tbCategoryBrandService;

    /**
     * 查询 品牌数据
     *
     * @param page   当前页码
     * @param rows   每页显示多少条
     * @param key    关键字  不必须
     * @param sortBy 排序字段 不必须
     * @param desc   是否降序
     * @return 品牌数据
     */
    @Override
    public PageResult<BrandDTO> searchPage(Integer page, Integer rows, String key, String sortBy, Boolean desc) {
        // mybatispuls 内置的分页查询
        Page<TbBrand> tbBrandPage = new Page<>(page, rows);
        // 构件查询条件
        QueryWrapper<TbBrand> wrapper = new QueryWrapper<>();
        // 搜索条件key 不是必须填写的，需要添加判断
        if (!StringUtils.isEmpty(key)) {
            // select * from 表 where name like "key" or letter like "key"
            // 搜索条件分为按照名字搜索和按照首字母搜索
            wrapper.lambda().like(TbBrand::getName, key).or().like(TbBrand::getLetter, key);
        }
        // 排序不是必须 需要判断
        if (!StringUtils.isEmpty(sortBy)) {
            // 区分降序和升序
            if (desc) {
                // desc 为true 表示升序
                tbBrandPage.setDesc(sortBy);
            } else {
                tbBrandPage.setAsc(sortBy);
            }
        }
        // 分页查询出的数据
        IPage<TbBrand> iPage = this.page(tbBrandPage, wrapper);
        // 异常判断
        if (iPage == null && CollectionUtils.isEmpty(iPage.getRecords())) {
            throw new LyException(ExceptionEnum.BRAND_NOT_FOUND);
        }
        // 数据 转换
        List<BrandDTO> brandDTOS = BeanHelper.copyWithCollection(iPage.getRecords(), BrandDTO.class);
        // 构建 PageResult

        return new PageResult<>(iPage.getTotal(), iPage.getPages(), brandDTOS);
    }

    /**
     * 品牌新增
     *
     * @param tbBrand 品牌数据
     * @param cids    分类id
     */
    @Override
    @Transactional // 表示开启事务
    public void saveBrand(TbBrand tbBrand, List<Long> cids) {
        // 保存品牌
        boolean save = this.save(tbBrand);
        // 保存失败会返回 flase
        if (!save) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
        // 维护分类和品牌的中间表
        // 1、获取当前品牌id
        Long brandId = tbBrand.getId();
        // 2、保存中间表判断是否选择分类
        if (!CollectionUtils.isEmpty(cids)) {
            // 中间表实体类
            saveCategoryBrand(cids, brandId);
        }
    }

    /**
     * 品牌 修改
     *
     * @param tbBrand 品牌数据
     * @param cids    分类id集合
     */
    @Override
    public void updateBrand(TbBrand tbBrand, List<Long> cids) {
        // 更新品牌表
        boolean b = this.updateById(tbBrand);
        if (!b) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        // 删除中间表数据
        // 1、获取品牌id
        Long brandId = tbBrand.getId();
        // 2、删除中间表数据
        deleteByBrandId(brandId);
        // 新增中间表数据
        saveCategoryBrand(cids, brandId);
    }

    /**
     * 删除品牌信息
     * 1、删除品牌信息
     * 2、删除中间表信息
     *
     * @param brandId 品牌id
     */
    @Override
    @Transactional // 开启事务
    public void deleteBrand(Long brandId) {
        // 1、删除品牌信息
        boolean b = this.removeById(brandId);
        if (!b) {
            throw new LyException(ExceptionEnum.DELETE_OPERATION_FAIL);
        }
        // 2、删除中间表信息
        deleteByBrandId(brandId);
    }

    /**
     * 新增商品时 根据分类查询所有品牌信息
     *
     * @param categoryId
     * @return
     */
    @Override
    public List<BrandDTO> queryByCategoryId(Long categoryId) {
        // 自己编写sql语句
        List<TbBrand> brandList = this.baseMapper.selectBrandJoinCategory(categoryId);
        if (CollectionUtils.isEmpty(brandList)) {
            throw new LyException(ExceptionEnum.BRAND_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(brandList, BrandDTO.class);
    }

    /**
     * TODO 根据品牌id查询  品牌
     *
     * @param id 品牌id
     */
    @Override
    public BrandDTO findByid(Long id) {
        TbBrand tbBrand = this.getById(id);
        if (tbBrand == null) {
            throw new LyException(ExceptionEnum.BRAND_NOT_FOUND);
        }
        return BeanHelper.copyProperties(tbBrand, BrandDTO.class);
    }

    @Override
    public List<BrandDTO> findBrandsByIds(List<Long> ids) {
        List<TbBrand> tbBrands = (List<TbBrand>) this.listByIds(ids);
        return BeanHelper.copyWithCollection(tbBrands, BrandDTO.class);
    }

    /**
     * 删除中间表数据
     *
     * @param brandId 品牌表
     */
    private void deleteByBrandId(Long brandId) {
        QueryWrapper<TbCategoryBrand> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbCategoryBrand::getBrandId, brandId);
        boolean remove = tbCategoryBrandService.remove(queryWrapper);
        if (!remove) {
            throw new LyException(ExceptionEnum.DELETE_OPERATION_FAIL);
        }
    }

    /**
     * 新增中间表数据
     *
     * @param cids    分类id集合
     * @param brandId 品牌id
     */
    private void saveCategoryBrand(List<Long> cids, Long brandId) {
        ArrayList<TbCategoryBrand> categoryBrandslist = new ArrayList<>();

        for (Long cid : cids) {
            // 根据分类id构建 中间表实体类
            TbCategoryBrand tbCategoryBrand = new TbCategoryBrand();
            tbCategoryBrand.setBrandId(brandId);
            tbCategoryBrand.setCategoryId(cid);
            // 将实体类添加到集合
            categoryBrandslist.add(tbCategoryBrand);
        }
        // mybatisPlus saveBatch 可以直接保存集合
        boolean b = tbCategoryBrandService.saveBatch(categoryBrandslist);
        if (!b) {
            // 如果保存失败 抛出异常
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }
}
